package com.dreamana.components
{
	import com.dreamana.ui.BaseComponent;
	import com.dreamana.ui.ISkinnable;
	import com.dreamana.ui.SkinGraphics;
	
	import flash.display.BitmapData;
	import flash.display.Graphics;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	
	[Event(name="scroll", type="flash.events.Event")]
	
	public class VSlider extends BaseComponent implements ISkinnable
	{
		protected var _track:Sprite;
		protected var _trackColor:int = -1;
		protected var _trackTexture:BitmapData;
		protected var _trackScale9Grid:Rectangle;
		
		protected var _dragger:Sprite;
		protected var _draggerColor:int = -1;
		protected var _draggerTexture:BitmapData;
		protected var _draggerScale9Grid:Rectangle;
		protected var _draggerWidth:int;
		protected var _draggerHeight:int;
		protected var _dragBounds:Rectangle = new Rectangle();
		protected var _dragging:Boolean = false;
		
		
		public function VSlider(w:int, h:int)
		{
			_width = w;
			_height = h;
			
			_draggerWidth = _width;
			_draggerHeight = _width;
			
			this.init();
		}
		
		override protected function addChildren():void
		{
			_track = new Sprite();
			this.addChild(_track);
			
			_dragger = new Sprite();
			this.addChild(_dragger);
			
			_track.addEventListener(MouseEvent.MOUSE_DOWN, onTrackDown);
			_dragger.addEventListener(MouseEvent.MOUSE_DOWN, onDrag);
		}
		
		//--- PUBLIC METHODS ---
		
		override public function draw():void
		{
			var g:Graphics;
			
			g = _track.graphics;
			g.clear();
			if(_trackTexture) {
				if(_trackScale9Grid) SkinGraphics.fill9Grid(g, _trackTexture, _width, _height, _trackScale9Grid, false);
				else SkinGraphics.fillRect(g, _trackTexture, _width, _height);
			}
			else if(_trackColor >= 0) {
				SkinGraphics.drawBlank(g, _width, _height, _trackColor);
			}
			else {
				SkinGraphics.drawWireFrame(g, _width, _height);
			}
			
			g = _dragger.graphics;
			g.clear();
			if(_draggerTexture) {
				if(_draggerScale9Grid) SkinGraphics.fill9Grid(g, _draggerTexture, _draggerWidth, _draggerHeight, _draggerScale9Grid, false);
				else SkinGraphics.fillRect(g, _draggerTexture, _draggerWidth, _draggerHeight);
			}
			else if(_draggerColor >= 0) {
				SkinGraphics.drawBlank(g, _draggerWidth, _draggerHeight, _draggerColor);
			}
			else {
				SkinGraphics.drawWireFrame(g, _draggerWidth, _draggerHeight);
			}
			
			//set bounds
			this.setDragBounds(_dragger.x, _track.y, _dragger.x, _track.height-_dragger.height);
		}
		
		override public function setStyle(style:String, value:Object):void
		{
			super.setStyle(style, value);
			
			switch(style) {
				case "track-color":
					_trackColor = value as Number;
					invalidate();
					break;
				case "track-image":
					_trackTexture = value as BitmapData;
					invalidate();
					break;
				case "track-9grid":
					_trackScale9Grid = value as Rectangle;
					invalidate();
					break;
				case "dragger-color":
					_draggerColor = value as Number;
					invalidate();
					break;
				case "dragger-image":
					_draggerTexture = value as BitmapData;
					invalidate();
					break;
				case "dragger-9grid":
					_draggerScale9Grid = value as Rectangle;
					invalidate();
					break;
			}
		}
		
		public function setDragBounds(ox:int, oy:int, w:int, h:int):void
		{
			_dragBounds.x = ox;
			_dragBounds.y = oy;
			_dragBounds.width = w;
			_dragBounds.height = h;
		}
		
		public function setDraggerSize(w:int, h:int):void
		{
			_draggerWidth = w;
			_draggerHeight = h;
			
			//bug fixed 2012-06-26
			//invalidate();
			draw();
		}
		
		public function scroll(delta:Number):void
		{
			if(percent + delta < 0) percent = 0;
			else if(percent + delta > 1) percent = 1;
			else percent += delta;
			
			this.dispatchEvent(new Event(Event.SCROLL));
		}
		
		//--- EVENT HANDLERS ---
		
		
		protected function onDrag(e:Event):void
		{
			_dragger.startDrag(false, _dragBounds);
			
			stage.addEventListener(MouseEvent.MOUSE_MOVE, onDragging);
			stage.addEventListener(MouseEvent.MOUSE_UP, onDrop);
			
			_dragging = true;
		}
		
		protected function onDrop(e:Event):void
		{
			_dragger.stopDrag();
			
			//dispatch final state
			this.dispatchEvent(new Event(Event.SCROLL));
			
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, onDragging);
			stage.removeEventListener(MouseEvent.MOUSE_UP, onDrop);
			
			_dragging = false;
		}
		
		protected function onDragging(e:Event):void
		{
			this.dispatchEvent(new Event(Event.SCROLL));
		}
		
		protected function onTrackDown(e:MouseEvent):void
		{
			var my:int = _track.mouseY - _dragger.height/2;
			
			var p:Number = (my - _dragBounds.y) / _dragBounds.height;
			p = p < 0 ? 0 : (p > 1 ? 1 : p);
			
			this.percent = p;
			
			this.dispatchEvent(new Event(Event.SCROLL));
		}
		
		//--- GETTER/SETTERS ---
		public function get percent():Number { return (_dragger.y - _dragBounds.y) / _dragBounds.height; }
		public function set percent(value:Number):void {
			_dragger.y = _dragBounds.y + Math.round( _dragBounds.height * value);
		}
		
		public function get dragging():Boolean { return _dragging; }
		public function get track():Sprite { return _track; }
		public function get dragger():Sprite { return _dragger; }
	}
}